package generator.workflow;


import generator.datastructure.MethodDeclaration;
import generator.util.input_interpreter.ParallelizerInterpreter;

import java.util.List;



/**De esta clase deberán heredar las que implementen los algoritmos SFJ y MFJ que análizan y transforman una clase
 * secuencial en una clase peer para hacer uso de una biblioteca de paralelización específica. {@link PeerClassDirector}
 * abstrae el orden en el que determinados pasos deben ser aplicados en la construcción de una clase peer,
 * independientemente del patrón de sincronización de que se trate (SFJ o MFJ). Los pasos a invocar son definidos
 * por la interface {@link PeerClassBuilder}.
 * Una clase peer es una clase que hace uso de los servicios de gridificación provistos por
 * algún middleware. 
 * PeerClassDirector en conjunto con PeerClassBuilder responden al patrón creacional Builder.
 * Este director debería ser utilizado por la implementación de un {@link Parallelizer} para 
 * obtener la clase peer.   
 * @author Hirsch-Fernández
 * */
public abstract class PeerClassDirector {
	

	/**instancia del builder que utiliza la clase para generar la clase peer*/
	protected PeerClassBuilder pcb;
	
	protected ParallelizerInterpreter pi;

	/**@param pcb
	 * 			el builder que utilizará el director para generar la clase peer*/
	public abstract void setPeerClassBuilder(PeerClassBuilder pcb);
	
	/**@return el builder que utiliza el director para generar la clase peer*/
	public abstract PeerClassBuilder getPeerClassBuilder();
	
	
	public ParallelizerInterpreter getParallelizerInterpreter() {
		return pi;
	}

	public void setParallelizerInterpreter(ParallelizerInterpreter pi) {
		this.pi = pi;
	}	

	/**Define el orden en el que las funciones definidas por un builder deben ser aplicadas
	 * para obtener una clase peer.
	 * @param pi
	 * 			lista de {@link MethodDeclaration} que indica qué métodos serán gridificados
	 * @return la clase peer generada*/
	public final void buildPeerClass(){
		if (pcb.loadSequentialClass(pi)){
			List<MethodDeclaration> msd = pi.getMethodsToParallelize();
			//por cada método a gridificar
			for (MethodDeclaration md : msd)
				parallelizeMethod(md);
		}
				
	}

	/**Este método debe ser implementado por la clase que defina el algoritmo de análisis y 
	 * transformación de código dependiendo del patrón de sincronización de resultados del que se trate.
	 * (SFJ o MFJ)
	 * @param md
	 * 			declaración del método divide y conquista recursivo que debe ser paralelizado*/
	protected abstract void parallelizeMethod(MethodDeclaration md);
	
}
